﻿using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using DevExpress.Web.ASPxTreeList;
using System.Collections.Generic;
using OT.Module.Model;
using OT.Module.BLL;
using OT.Common;
using OT.Dev;

public partial class Common_HugeTree : DevPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack && !IsCallback)
        {
            // 风格设置
            InitTreeStyle(treeList);

            // 展开树顶级节点
            // VirtualModeCreateChildren和VirtualModeNodeCreating
            // 将早于Page_Load完成调用，因此可在这里进行树的展开
            treeList.ExpandToLevel(1);
        }
    }

    /***    Help
     * 
     * 注意：本页面的代码是为了清晰的说明Virtual Mode模式，没有经过优化
     *       不允许作为标准模型复制使用！！！
     * 
     * 下面展示的是Virtual Mode模式如何建立树
     * 用于以下场景：
     * 1) 树具有海量节点，不适合一次性全部载入
     * 2) 树节点的建立成本高
     * 
     * TreeList先后调用下面两个事件完成树的建立
     * 
     * VirtualModeCreateChildren 
     *    用于根据父节点的数据对象类型建立子节点的数据对象列表
     *    这里不是直接建立树节点，而是建立与树型相匹配的对象模型
     * 
     * VirtualModeNodeCreating
     *    根据数据对象建立节点
     */
    protected void treeList_VirtualModeCreateChildren(object sender, TreeListVirtualModeCreateChildrenEventArgs e)
    {
        // e.NodeObject==null代表要求建立树的最顶级节点
        if (e.NodeObject == null)
        {
            // e.Children是代表要建立的子节点列表
            // 接受一个支持IList接口的集合
            // 因此childs也可以是任意的List<object>形式
            // 这里直接使用Id
            List<string> childs = new List<string>();
            childs.Add("T0");
            e.Children = childs;
            return;
        }

        // 因为该事件会多次调用，这里应当是以缓存的方式提供数据才合理
        // 如果直接使用数据库调用会造成性能瓶颈
        Dictionary<string, List<Category>> dict = new Category_BLL(XpoSession).GetCategoryDictionary();
        
        // 获得节点的数据对象，这里是ID
        string key = e.NodeObject.ToString();
        if (key == "T0")
        {
            // 对于公司节点，要建立[全部分类]节点和顶级分类节点

            // 建立[全部分类]节点
            List<string> childs = new List<string>();
            childs.Add("0");

            // 建立顶级分类节点
            if (dict.ContainsKey(string.Empty))
            {
                List<Category> categorys = dict[string.Empty];
                foreach (Category category in categorys)
                    childs.Add(category.ID);
            }
            e.Children = childs;
        }
        else if (key == "0")
        {
            // [全部分类]节点，没有子节点
        }
        else
        {
            // 其它分类节点则，获得下级分类节点
            List<string> childs = new List<string>();
            // 建立子分类节点
            if (dict.ContainsKey(key))
            {
                List<Category> categorys = dict[key];
                foreach (Category category in categorys)
                {
                    childs.Add(category.ID);
                }
            }
            e.Children = childs;
        }
    }

    protected void treeList_VirtualModeNodeCreating(object sender, TreeListVirtualModeNodeCreatingEventArgs e)
    {
        // 每个要显示的节点都要调用一次该事件
        // 因此事件中数据库的访问必须是使用缓存的方式
        // 因为是短时间内多次访问，
        // 这里需要一种定期内不需要即时检测数据库更新的缓存技术
        Dictionary<string, List<Category>> dict = new Category_BLL(XpoSession).GetCategoryDictionary();
        Dictionary<string, Category> dictKey = new Category_BLL(XpoSession).GetKeyDictionary();

        // 获得数据节点
        string nodekey = e.NodeObject.ToString();
        // 确定树节点的唯一键值，这里因为nodekey是ID，可以直接用作键值
        e.NodeKeyValue = nodekey;

        // 确定该节点是否为子节点，这一判断很重要
        // 如果做出了错误判断，那么树节点就无法继续展开了
        if (nodekey == "T0")
            e.IsLeaf = false;
        else
            e.IsLeaf = !dict.ContainsKey(nodekey);

        // 指定节点中的键值对，用于树界面数据的绑定
        // 这里要注意的是，树并不是直接和数据对象绑定获得数据
        // 而是要转换为键值对的形式，另一种Unbound模式也是一样的
        string name = "";
        string iconName = GIcon.分类;
        if (nodekey == "T0")
        {
            name = "公司";
            iconName = GIcon.公司;
        }
        else if (nodekey == "0")
            name = "全部分类";
        else
            name = dictKey[nodekey].Name;

        e.SetNodeValue("Name", name);
        e.SetNodeValue("IconName", iconName);
    }

}
